home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_001 / balls / balls.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  15KB  |  477 lines

  1. #include <exec/types.h>
  2. #include <libraries/mathffp.h>
  3. #include <graphics/gfxbase.h>
  4. #include <intuition/intuition.h>
  5. #undef   NULL
  6. #include <stdio.h>
  7.  
  8. /*
  9. **    balls - a simulation of that kinetic thingy with three-d
  10. **            smooth shaded  spheres with diffuse and specular
  11. **            reflections. It'd be  nice if someone could  add
  12. **            sound. A good demonstration  of  using  the  ffp
  13. **            math subroutines.  I plan to add texture mapping
  14. **            to the spheres in the future.
  15. **
  16. **
  17. **    perry s. kivolowitz - ihnp4!ptsfa!well!perry
  18. **
  19. **    not to be distributed for commercial purposes. any
  20. **    distribution must include this notice, please.
  21. **
  22. */
  23.  
  24. #ifdef   MY_DEBUG
  25. FILE *dfp;
  26. #endif
  27.  
  28. #define  RADIUS   20       /* radius of the balls ve are goink to draw */
  29. #define  DEPTH    5        /* number of pixel planes */
  30. #define  NMAP     32       /* 2 to the DEPTH power   */
  31. #define  AMBIENT  2        /* how much light on the dark side ofthe moon */
  32. #define  NSTEPS   6        /* how many discreet frames in bouncers */
  33.  
  34. #define  SH       200      /* screen height */
  35. #define  SW       320      /* screen width  */
  36. #define  WH       (SH-10)  /* window height */
  37. #define  WW       SW       /* window width  */
  38. #define  MW       (WW / 2) /* middle of window */
  39.  
  40. #define  D        (2 * RADIUS)
  41.  
  42. struct IntuitionBase *IntuitionBase;
  43. struct GfxBase *GfxBase;
  44. int    MathBase;
  45. int    MathTransBase;
  46.  
  47. int is_cli = 0;
  48.  
  49. struct Window *w;                  /* window structure returned by exec */
  50. struct Screen *s;                  /* screen structure returned by exec */
  51. struct ColorMap *color_map;        /* pointer to c_map returned by exec */
  52. short  displacements[D];           /* place for sphere's scanline dx's  */
  53. short  surface[D];                 /* place for spehre's scanline dz's  */
  54.  
  55. extern int SPAdd() , SPSub() , SPMul() , SPDiv() , SPNeg() ;
  56. extern int SPFix() , SPFlt() , SPCmp() , SPTst() , SPAbs() ;
  57. extern int SPSqrt() , SPFieee() , SPTieee();
  58. extern int SPSin() , SPCos() , SPPow();
  59.  
  60. union kludge {
  61.    float f;
  62.    int   i;
  63. };
  64.  
  65. struct bouncer {
  66.    struct RastPort rp;
  67.    struct BitMap   bm;
  68.    int sx , sy;
  69. } left[NSTEPS] , right[NSTEPS];
  70.  
  71. struct point {
  72.    union kludge x;
  73.    union kludge y;
  74.    union kludge z;
  75. } light;
  76.  
  77. /*
  78. ** mask is a bit mask of things that I should close or deallocate
  79. ** when the program terminates for  any reason.  after opening or
  80. ** allocating some resource set the appropriate bit in mask.
  81. */
  82.  
  83. unsigned int mask = 0;
  84.  
  85. #define  INTUITION   0x00000001
  86. #define  GRAPHICS    0x00000002
  87. #define  SCREEN      0x00000004
  88. #define  WINDOW      0x00000008
  89. #define  COLORMAP    0x00000010
  90. #define  MATH        0x00000020
  91. #define  MATHTRANS   0x00000040
  92.  
  93. int rastcount = 0;      /* easy way to free rasters at termination */
  94.  
  95. struct NewScreen ns = {    /*****************/
  96.    0 ,                     /* LeftEdge      */
  97.    0 ,                     /* TopEdge       */
  98.    SW ,                    /* Width         */
  99.    SH ,                    /* Height        */
  100.    DEPTH ,                 /* Depth         */
  101.    0 ,                     /* DetailPen     */
  102.    1 ,                     /* BlockPen      */
  103.    0 ,                     /* ViewModes     */
  104.    CUSTOMSCREEN ,          /* Type          */
  105.    NULL ,                  /* *Font         */
  106.    " spheres by p.s.kivolowitz" ,       /* *DefaultTitle */
  107.    NULL ,                  /* *Gadgets      */
  108.    NULL                    /* *CustomBitMap */
  109. };                         /*****************/
  110.  
  111. struct NewWindow nw = {    /*****************/
  112.    0 ,                     /* LeftEdge      */
  113.    10 ,                    /* TopEdge       */
  114.    WW ,                    /* Width         */
  115.    WH ,                    /* Height        */
  116.    -1 ,                    /* DetailPen     */
  117.    -1 ,                    /* BlockPen      */
  118.    CLOSEWINDOW ,           /* IDCMP---Flags */
  119.    WINDOWCLOSE             /*   F           */
  120.    | BACKDROP              /*     l         */
  121.    | BORDERLESS            /*       a       */
  122.    | NOCAREREFRESH         /*         g     */
  123.    | ACTIVATE ,            /*           s   */
  124.    NULL ,                  /* *FirstGadget  */
  125.    NULL ,                  /* *CheckMark    */
  126.    "(still under development)" ,/* *Title        */
  127.    NULL ,                  /* *Screen       */ /* to be filled in */
  128.    NULL ,                  /* *BitMap       */
  129.    0 ,                     /* MinWidth      */
  130.    0 ,                     /* MinHeight     */
  131.    0 ,                     /* MaxWidth      */
  132.    0 ,                     /* MaxHeight     */
  133.    CUSTOMSCREEN            /* Type          */
  134. };                         /*****phew!!!*****/
  135.  
  136. float convert(i)
  137. {
  138.    union kludge k;
  139.  
  140.    k.i = SPTieee(i);
  141.    return(k.f);
  142. }
  143.  
  144. degrad(degrees)
  145. {
  146.    union kludge pi;
  147.  
  148.    pi.f = 355.0 / 113.0;   /* chinese approximation */
  149.    pi.i = SPMul(SPFieee(pi.i) , SPFlt(degrees));
  150.    return(SPDiv(SPFlt(180) , pi.i));
  151. }
  152.  
  153. main(argc , argv)
  154. char *argv[];
  155. {
  156.    int i;
  157.    struct IntuiMessage *message;
  158.    if (argc) is_cli = 1;
  159.  
  160. #ifdef   MY_DEBUG
  161.    if ((dfp = fopen("debug.file" , "w")) == NULL) {
  162.       if (is_cli) printf("can't open debugging file\n");
  163.       exit(1);
  164.    }
  165.    fprintf(dfp,"debugging information\n");
  166.    fflush(dfp);
  167. #endif
  168.  
  169.    if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)))
  170.    {
  171.       if (is_cli) printf("no graphics library!!!\n");
  172.       close_things();
  173.       exit(1);
  174.    }
  175.    mask |= GRAPHICS;
  176.  
  177.    if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library"))) {
  178.       if (is_cli) printf("no intuition here!!\n");
  179.       close_things();
  180.       exit(1);
  181.    }
  182.    mask |= INTUITION;
  183.  
  184.    if ((MathBase = OpenLibrary("mathffp.library" , 0)) == NULL) {
  185.       if (is_cli) printf("couldn't open mathffp library\n");
  186.       close_things();
  187.       exit(1);
  188.    }
  189.    mask |= MATH;
  190.  
  191.    if ((MathTransBase = OpenLibrary("mathtrans.library" , 0)) == NULL) {
  192.       if (is_cli) printf("couldn't open mathtrans library\n");
  193.       close_things();
  194.       exit(1);
  195.    }
  196.    mask |= MATHTRANS;
  197.  
  198.    allocate_rasters();
  199.  
  200.    if ((s = (struct Screen *) OpenScreen(&ns)) == (struct Screen *) NULL) {
  201.       if (is_cli) printf("could not open the screen!\n");
  202.       close_things();
  203.       exit(2);
  204.    }
  205.    mask |= SCREEN;
  206.    nw.Screen = s;
  207.  
  208.    if((w = (struct Window *)OpenWindow(&nw)) == (struct Window *) NULL) {
  209.       if (is_cli) printf("could not open the window!\n");
  210.       close_things();
  211.       exit(2);
  212.    }
  213.    mask |= WINDOW;
  214.  
  215.    init_color_map();
  216.  
  217.    light.x.f = 0.0;
  218.    light.y.f = light.x.f + 150.0 - light.x.f;
  219.    light.z.f = light.x.f + 25.0 - light.x.f;
  220.  
  221.    light.x.i = SPFieee(light.x.i);  /*                             */
  222.    light.y.i = SPFieee(light.y.i);  /* convert light vector to FFP */
  223.    light.z.i = SPFieee(light.z.i);  /*                             */
  224.  
  225.    bres(RADIUS , displacements);
  226.  
  227.    /*
  228.    ** make the three bottom balls
  229.    */
  230.  
  231.    make_ball(w->RPort , MW - D , WH - RADIUS , -D , 0 , 0);
  232.    make_ball(w->RPort , MW     , WH - RADIUS ,  0 , 0 , 0);
  233.    make_ball(w->RPort , MW + D , WH - RADIUS ,  D , 0 , 0);
  234.  
  235.    make_rotated_ball(&left[0] , -15 , MW - 2 * D , 10 , WH - 10 - RADIUS);
  236.    make_rotated_ball(&right[0] , 15 , MW + 2 * D , 10 , WH - 10 - RADIUS);
  237.    make_rotated_ball(&left[1] , -14 , MW - 2 * D , 10 , WH - 10 - RADIUS);
  238.    make_rotated_ball(&right[1] , 14 , MW + 2 * D , 10 , WH - 10 - RADIUS);
  239.    make_rotated_ball(&left[2] , -12 , MW - 2 * D , 10 , WH - 10 - RADIUS);
  240.    make_rotated_ball(&right[2] , 12 , MW + 2 * D , 10 , WH - 10 - RADIUS);
  241.    make_rotated_ball(&left[3] , -9  , MW - 2 * D , 10 , WH - 10 - RADIUS);
  242.    make_rotated_ball(&right[3],  9  , MW + 2 * D , 10 , WH - 10 - RADIUS);
  243.    make_rotated_ball(&left[4] , -5  , MW - 2 * D , 10 , WH - 10 - RADIUS);
  244.    make_rotated_ball(&right[4],  5  , MW + 2 * D , 10 , WH - 10 - RADIUS);
  245.    make_rotated_ball(&left[5] ,  0  , MW - 2 * D , 10 , WH - 10 - RADIUS);
  246.    make_rotated_ball(&right[5],  0  , MW + 2 * D , 10 , WH - 10 - RADIUS);
  247.  
  248.    ClipBlit(&left[0].rp,0,0,w->RPort,left[0].sx,left[0].sy,D,D,0xC0);
  249.    ClipBlit(&right[NSTEPS-1].rp,0,0,w->RPort,right[NSTEPS-1].sx,
  250.     right[NSTEPS-1].sy,D,D,0xC0);
  251.  
  252.    message = (struct IntuiMessage *) GetMsg(w->UserPort);
  253.    while (!message || (message->Class != CLOSEWINDOW)) {
  254.       for (i = 1; i < NSTEPS; i++) {
  255.          Delay(2);
  256.          WaitBOVP(&s->ViewPort);
  257.          clear_rect(w->RPort,left[i-1].sx,left[i-1].sy,D,D);
  258.          ClipBlit(&left[i].rp,0,0,w->RPort,left[i].sx,left[i].sy,D,D,0xC0);
  259.       }
  260.       for (i = NSTEPS-2; i >= 0; i--) {
  261.          WaitBOVP(&s->ViewPort);
  262.          clear_rect(w->RPort,right[i+1].sx,right[i+1].sy,D,D);
  263.          ClipBlit(&right[i].rp,0,0,w->RPort,right[i].sx,right[i].sy,D,D,0xC0);
  264.          Delay(2);
  265.       }
  266.       Delay(1);
  267.       for (i = 1; i < NSTEPS; i++) {
  268.          Delay(2);
  269.          WaitBOVP(&s->ViewPort);
  270.          clear_rect(w->RPort,right[i-1].sx,right[i-1].sy,D,D);
  271.          ClipBlit(&right[i].rp,0,0,w->RPort,right[i].sx,right[i].sy,D,D,0xC0);
  272.       }
  273.       for (i = NSTEPS-2; i >= 0; i--) {
  274.          WaitBOVP(&s->ViewPort);
  275.          clear_rect(w->RPort,left[i+1].sx,left[i+1].sy,D,D);
  276.          ClipBlit(&left[i].rp,0,0,w->RPort,left[i].sx,left[i].sy,D,D,0xC0);
  277.          Delay(2);
  278.       }
  279.       Delay(1);
  280.       message = (struct IntuiMessage *) GetMsg(w->UserPort);
  281.    }
  282.  
  283. #ifdef   MY_DEBUG
  284.    fclose(dfp);
  285. #endif
  286.  
  287.    close_things();
  288.    exit(0);
  289. }
  290.  
  291. clear_rect(rp , sx , sy , dx , dy)
  292. struct RastPort *rp;
  293. {
  294.    ClipBlit(rp,sx,sy,rp,sx,sy,dx,dy,0x20);
  295. }
  296.  
  297. make_rotated_ball(b , degrees , cx , cy , length)
  298. struct bouncer *b;
  299. {
  300.    int dx , dy;
  301.  
  302.    dx = SPMul(SPFlt(length) , SPSin(degrad(abs(degrees))));
  303.    dy = SPMul(SPFlt(length) , SPCos(degrad(abs(degrees))));
  304.    b->sx = cx + ((degrees < 0) ? -SPFix(dx) : SPFix(dx));
  305.    b->sy = cy + SPFix(dy);
  306.    make_ball(&b->rp , RADIUS , RADIUS , b->sx - MW , WH - RADIUS - b->sy , 0);
  307.    b->sx -= RADIUS;
  308.    b->sy -= RADIUS;
  309. }
  310.  
  311. close_things()
  312. {
  313.    if (rastcount) deallocate_rasters();
  314.    if (mask & WINDOW)    CloseWindow(w);
  315.    if (mask & SCREEN)    CloseScreen(s);
  316.    if (mask & GRAPHICS)  CloseLibrary(GfxBase);
  317.    (void) OpenWorkBench();
  318.    if (mask & INTUITION) CloseLibrary(IntuitionBase);
  319. }
  320.  
  321. init_color_map()
  322. {
  323.    static short map_values[NMAP] = {
  324.       /* format 0x0RGB */   /* ooooooooh ychhhhhh! fix this later! */
  325.       /* 0  */  0x0430 , 
  326.       /* 1  */  0x0FFF ,
  327.       /* 2  */  0x0F01 ,
  328.       /* 3  */  0x0F11 ,
  329.       /* 4  */  0x0F12 ,
  330.       /* 5  */  0x0F22 ,
  331.       /* 6  */  0x0F23 ,
  332.       /* 7  */  0x0F33 ,
  333.       /* 8  */  0x0F34 ,
  334.       /* 9  */  0x0F44 ,
  335.       /* 10 */  0x0F45 ,
  336.       /* 11 */  0x0F55 ,
  337.       /* 12 */  0x0F56 ,
  338.       /* 13 */  0x0F66 ,
  339.       /* 14 */  0x0F67 ,
  340.       /* 15 */  0x0F77 ,
  341.       /* 16 */  0x0F78 ,
  342.       /* 17 */  0x0F88 ,
  343.       /* 18 */  0x0F89 ,
  344.       /* 19 */  0x0F99 ,
  345.       /* 20 */  0x0F9A ,
  346.       /* 21 */  0x0FAA ,
  347.       /* 22 */  0x0FAB ,
  348.       /* 23 */  0x0FBB ,
  349.       /* 24 */  0x0FBC ,
  350.       /* 25 */  0x0FCC ,
  351.       /* 26 */  0x0FCD ,
  352.       /* 27 */  0x0FDD ,
  353.       /* 28 */  0x0FDE ,
  354.       /* 29 */  0x0FEE ,
  355.       /* 30 */  0x0FEF ,
  356.       /* 31 */  0x0FFF
  357. };
  358.    LoadRGB4(&s->ViewPort , map_values , NMAP);
  359. }
  360.  
  361. normalize(p)
  362. struct point *p;
  363. {
  364.    union kludge length;
  365.    int xsquared, ysquared, zsquared;
  366.  
  367.    xsquared = SPMul (p -> x.i, p -> x.i);
  368.    ysquared = SPMul (p -> y.i, p -> y.i);
  369.    zsquared = SPMul (p -> z.i, p -> z.i);
  370.    length.i = SPSqrt (SPAdd (SPAdd (xsquared, ysquared), zsquared));
  371.  
  372.    p->x.i = SPDiv(length.i , p->x.i);
  373.    p->y.i = SPDiv(length.i , p->y.i);
  374.    p->z.i = SPDiv(length.i , p->z.i);
  375. }
  376.  
  377.  
  378. make_ball(rp , basex , basey , cx , cy , cz)
  379. struct RastPort *rp;
  380. {
  381.    int I , scanline;
  382.    int twelve , x , y;
  383.    struct point H , l;
  384.    struct point pnt;
  385.    union kludge tmp , rad , d;
  386.  
  387.  
  388.    rad.i = SPDiv(SPFlt(RADIUS) , SPFlt(1));
  389.  
  390.    basex -= RADIUS;
  391.    basey -= RADIUS;
  392.    twelve = SPFlt(12);
  393.    l.x.i = SPSub(SPFlt(cx) , light.x.i);  /* translate light source to */
  394.    l.y.i = SPSub(SPFlt(cy) , light.y.i);  /* make center of sphere the */
  395.    l.z.i = SPSub(SPFlt(cz) , light.z.i);  /* origin relative to light  */
  396.    normalize(&l);
  397.  
  398.    for (scanline = 0; scanline < 2 * RADIUS; scanline++) {
  399.       register int r;
  400.       register int i;
  401.  
  402.       r = displacements[scanline];
  403.       y = scanline + basey;
  404.       pnt.y.i = SPMul(SPFlt(RADIUS - scanline) , rad.i);
  405.       bres(r , surface);
  406.       for (i = 0; i < 2 * r; i++) {
  407.          pnt.x.i = SPMul(SPFlt(-r + i) , rad.i);
  408.          pnt.z.i = SPMul(SPFlt(surface[i]) , rad.i);
  409.      d.i = SPAdd(SPMul(pnt.x.i , l.x.i) , SPMul(pnt.y.i, l.y.i));
  410.      d.i = SPAdd(d.i , SPMul(pnt.z.i , l.z.i));
  411.          I = AMBIENT;
  412.          tmp.i = SPTieee(d.i);
  413.          if (tmp.f > 0.0) {
  414.             I += SPFix(SPMul(d.i , SPFlt(NMAP - AMBIENT)));
  415.             H.x.i = l.x.i;
  416.             H.y.i = l.y.i;
  417.             H.z.i = SPAdd(SPFlt(1) , l.z.i);
  418.             normalize(&H);
  419.             /* reusing d */
  420.         d.i = SPAdd(SPMul(H.x.i , pnt.x.i), SPMul(H.y.i , pnt.y.i));
  421.         d.i = SPAdd(d.i, SPMul(H.z.i , pnt.z.i)); 
  422.             d.i = SPPow(twelve , d.i);
  423.             tmp.i = SPTieee(d.i);
  424.             if (tmp.f > 0.0) I += SPFix(SPMul(d.i , twelve));
  425.          }
  426.          x = RADIUS - r + i + basex;
  427.          if (I >= NMAP) I = NMAP - 1;
  428.          SetAPen(rp , I);
  429.          (void) WritePixel(rp , x , y);
  430.       }
  431.    }
  432. }
  433.  
  434. allocate_rasters()
  435. {
  436.    int i , j;
  437.  
  438.    for (i = 0; i < NSTEPS; i++) {
  439.       InitRastPort(&left[i].rp);
  440.       InitRastPort(&right[i].rp);
  441.       InitBitMap(&left[i].bm , DEPTH , D , D);
  442.       InitBitMap(&right[i].bm , DEPTH , D , D);
  443.       for (j = 0; j < DEPTH; j++) {
  444.          left[i].bm.Planes[j] = AllocRaster(D , D);
  445.          if (left[i].bm.Planes[j] == NULL) {
  446. outer:      if (is_cli) printf("cannot allocate raster space\n");
  447.             close_things();
  448.             exit(1);
  449.          }
  450.          rastcount++;
  451.          right[i].bm.Planes[j] = AllocRaster(D , D);
  452.          if (right[i].bm.Planes[j] == NULL) goto outer;
  453.          rastcount++;
  454.       }
  455.       left[i].rp.BitMap = &left[i].bm;
  456.       right[i].rp.BitMap = &right[i].bm;
  457.       SetRast(&left[i].rp , 0);
  458.       SetRast(&right[i].rp , 0);
  459.    }
  460. }
  461.  
  462. deallocate_rasters()
  463. {
  464.    int i , j;
  465.  
  466.    for (i = 0; i < NSTEPS && rastcount >= 0; i++) {
  467.       for (j = 0; j < DEPTH && rastcount >= 0; j++) {
  468.          if (rastcount-- == 0) continue;
  469.          FreeRaster(left[i].bm.Planes[j] , D , D);
  470.          if (rastcount-- == 0) continue;
  471.          FreeRaster(right[i].bm.Planes[j] , D , D);
  472.       }
  473.    }
  474. }
  475.  
  476.  
  477.